import { forwardRef, memo, useImperativeHandle } from "react";
import { Form, Button, Row, Col } from "antd";
import type { BaseOptionType, DefaultOptionType } from "antd/es/select";
import { useProForm } from "./useFrom";
import type { FormInstance } from "antd/es/form";
import type { CheckboxOptionType, UploadFile, UploadProps, GetProp } from "antd";
import {
	FromInput,
	FromSelect,
	FromDatePicker,
	FromCheckbox,
	FromInputNumber,
	FromRadio,
	FromSwitch,
	FromTreeSelect,
	FromUpload,
} from "./components/form-element";
import type { Dayjs } from "dayjs";
interface RuleConfig {
	message?: string;
	required?: boolean;
	pattern?: RegExp;
	type?: string; // 常见有 string |number |boolean |url | email
	min?: number; // 必须设置 type：string 类型为字符串最小长度；number 类型时为最小值；array 类型时为数组最小长度
	max?: number; // 必须设置 type：string 类型为字符串最大长度；number 类型时为最大值；array 类型时为数组最大长度
	len?: number; // string 类型时为字符串长度；number 类型时为确定数字； array 类型时为数组长度
	validator?: (rule: RuleConfig, value: any) => void;
}

export type FileType = Parameters<GetProp<UploadProps, "beforeUpload">>[0];

type Rule = RuleConfig | ((form: FormInstance) => RuleConfig) | any;

type TreeDataType = Array<{
	value: string;
	title: string;
	children?: Array<{
		value: string;
		title: string;
		children?: Array<{ value: string; title: string }>;
	}>;
	disabled?: boolean;
	disableCheckbox?: boolean;
}>;

export interface ShowUploadListInterface<T = any> {
	extra?: React.ReactNode | ((file: UploadFile<T>) => React.ReactNode);
	showRemoveIcon?: boolean | ((file: UploadFile<T>) => boolean);
	showPreviewIcon?: boolean | ((file: UploadFile<T>) => boolean);
	showDownloadIcon?: boolean | ((file: UploadFile<T>) => boolean);
	removeIcon?: React.ReactNode | ((file: UploadFile<T>) => React.ReactNode);
	downloadIcon?: React.ReactNode | ((file: UploadFile<T>) => React.ReactNode);
	previewIcon?: React.ReactNode | ((file: UploadFile<T>) => React.ReactNode);
}

export interface FormItem {
	name: string; // 表单项名称
	type:
		| "input" //输入框
		| "select" // 选择框
		| "date" // 日期
		| "checkbox" // 多选
		| "inputNumber" // 数字输入
		| "radio" // 单选
		| "switch" // 开关
		| "treeSelect" //树状选择
		| "upload"; // 表单项类型
	label?: string;
	placeholder?: string; // 表单项提示
	options?:
		| (BaseOptionType | DefaultOptionType)[]
		| undefined
		| CheckboxOptionType<string>[]
		| string[]
		| number[]
		| Array<CheckboxOptionType>; // 表单项选项
	initialValue?: string | number | boolean | Dayjs[] | undefined; // 表单项初始值
	value?: any; // 表单项值
	rules?: Rule[]; // 表单项验证规则
	render?: () => React.ReactNode; // 表单项渲染
	span?: number; // 表单项列宽
	picker?: "date" | "week" | "month" | "quarter" | "year"; // 日期选择器类型
	format?: string; // 日期选择器格式
	showTime?: boolean; // 日期选择器是否显示时间
	isDateRange?: boolean; // 是否是联动选择时间
	hidden?: boolean; // 表单项是否隐藏
	disabled?: boolean; // 表单项是否禁用
	readonly?: boolean; // 表单项是否只读
	onChange?: (e: any, label?: any, extra?: any) => void; // 表单项变化回调
	rangeName?: string[]; // 范围的key
	allowClear?: boolean | { clearIcon: React.ReactNode }; // 表单项是否允许清空
	inputType?: "input" | "textarea"; // 表单项类型
	min?: number; // 最小值, 用于inputNumber
	max?: number; // 最大值, 用于inputNumber
	treeCheckable?: boolean; //  树选择显示 Checkbox
	treeData?: TreeDataType;
	action?: string;
	uploadText?: string; // 上传按钮文本
	defaultFileList?: UploadFile[]; // 上传列表
	fileList?: UploadFile[];
	listType?: "text" | "picture" | "picture-card"; // 上传列表类型
	uplaodBtnRender?: () => React.ReactNode; // 自定义上传按钮渲染
	previewImage?: boolean; // 是否展示预览
	maxFileSize?: number; // 最大文件大小
	fileType?: string[]; // 文件类型
	maxCount?: number;
	showUploadList?: ShowUploadListInterface; // 上传列表 是否展示文件列表, 可设为一个对象，用于单独设定 extra(5.20.0+), showPreviewIcon, showRemoveIcon, showDownloadIcon, removeIcon 和 downloadIcon
}

type LayoutType = {
	labelCol?: { span: number };
	wrapperCol?: { span: number };
	layout?: "horizontal" | "vertical" | "inline";
};

interface ProFormProps<T> {
	formItems: FormItem[]; // 表单项
	saveBtnText?: string; // 保存按钮文本
	cancelBtnText?: string; // 取消按钮文本
	isShowCancelBtn?: boolean; // 是否显示取消按钮
	onFinish?: (e: T) => void; // 表单提交
	layout?: LayoutType; // 表单布局
	closeModal?: () => void; // 关闭模态框
}

// 表单组件的 ref 类型
interface ProFormRef<T> {
	formItemNew: FormItem[];
	resetForm?: () => void;
	setFromFieldsValue?: (values: T) => void;
}

// 自定义表单组件
const ProForm = memo(
	forwardRef(<T extends object = any>(props: ProFormProps<T>, ref: React.ForwardedRef<ProFormRef<T>>) => {
		// 暴露给父组件的属性
		useImperativeHandle(ref, () => ({
			formItemNew,
			resetForm,
			setFromFieldsValue,
		}));

		// 内部属性
		const {
			form,
			defaultSpan,
			onFinish,
			closeModal,
			formItemNew,
			initialValues,
			formLayout,
			resetForm,
			setFromFieldsValue,
		} = useProForm({
			...props,
		});
		const normFile = (e: any) => {
			if (Array.isArray(e)) {
				return e;
			}
			return e?.fileList;
		};
		return (
			<div>
				<Form form={form} initialValues={initialValues} onFinish={onFinish} {...formLayout}>
					<Row gutter={16} className="w-full">
						{formItemNew?.length &&
							formItemNew?.map((item: FormItem) => {
								const render = item?.render;
								return (
									<Col span={item?.span ?? defaultSpan} key={item.name}>
										<Form.Item
											name={item.name}
											label={item?.label}
											rules={item?.rules}
											getValueFromEvent={item?.type === "upload" ? normFile : undefined}
											valuePropName={item?.type === "upload" ? "fileList" : undefined}
										>
											{/* 输入框 */}
											{item.type === "input" && (render ? render() : <FromInput {...item} />)}
											{/* 下拉选择器 */}
											{item.type === "select" && <FromSelect {...item} />}
											{/* 日期选择器 */}
											{item.type === "date" && <FromDatePicker {...item} />}
											{/* 复选框 */}
											{item.type === "checkbox" && <FromCheckbox {...item} />}
											{/* 数字输入框 */}
											{item.type === "inputNumber" && <FromInputNumber {...item} />}
											{/* 单选框 */}
											{item.type === "radio" && <FromRadio {...item} />}
											{/* 开关 */}
											{item.type === "switch" && <FromSwitch {...item} />}
											{/* 树选择器 */}
											{item.type === "treeSelect" && <FromTreeSelect {...item} />}
											{/* 上传 */}
											{item.type === "upload" && <FromUpload {...item} />}
										</Form.Item>
									</Col>
								);
							})}

						{/* 保存按钮 */}
						<Col span={24} className="flex justify-end">
							<Form.Item>
								<div className="flex gap-2 items-center justify-end">
									<Button type="default" onClick={closeModal}>
										{props?.cancelBtnText ?? "取消"}
									</Button>
									<Button type="primary" htmlType="submit">
										{props?.saveBtnText ?? "确定"}
									</Button>
								</div>
							</Form.Item>
						</Col>
					</Row>
				</Form>
			</div>
		);
	}),
) as <T extends object = any>(props: ProFormProps<T> & { ref?: React.Ref<ProFormRef<T>> }) => React.ReactElement;

export default ProForm;
